#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <iostream>
#include <vector>
#include <thread>
#include "global.h"

using namespace std;

class server
{
    private:
        int server_port;//服务端口号
        int server_sockfd;//设为listen状态的套接字描述符
        string server_ip;//服务器ip
        vector<int> sock_arr; //保存所有套接字描述符
    public:
        server(int port,string ip);//构造函数
        ~server();       //析构函数
        void run();      //服务器开始服务
        static void RecvMsg(int conn);//子线程工作的静态函数
};
//构造
server::server(int port,string ip):server_port(port),server_ip(ip){}
//析构
server::~server(){
    for(auto conn:sock_arr)
       close(conn);
    close(server_sockfd);
}
//服务器开始服务
void server::run(){
    //1.定义sockfd
    server_sockfd=socket(AF_INET,SOCK_STREAM,0);
    //定义sockaddr_in
    struct sockaddr_in server_sockaddr;
    server_sockaddr.sin_family=AF_INET;
    server_sockaddr.sin_port= htons(server_port);
    server_sockaddr.sin_addr.s_addr=inet_addr(server_ip.c_str());//ip

    //2.bind 成功返回0，失败返回-1;
    if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1){
        perror("bind");//输出错误原因
        exit(1); //结束
    }
    //3. listen
    if(listen(server_sockfd,20)==-1)
    {
        perror("listen");
        exit(1);
    }
    //客户端套接字
    struct sockaddr_in client_addr;
    socklen_t length =sizeof(client_addr);

    //4. 不断取出新连接并创建子线程为其服务
    while(1){
        int conn =accept(server_sockfd,(struct sockaddr*)&client_addr,&length);
        if(conn<0)
        {
            perror("connect");//输出错误原因
            exit(1);//结束
        }
        cout<<"文件描述符为"<<conn<<"客户端成功连接\n";
        sock_arr.push_back(conn);
        //创建线程
         thread t(server::RecvMsg, conn);
        t.detach();//置为分离状态，不能用join，join会导致主线程阻塞
    }
}

//子线程工作的静态函数
//
void server::RecvMsg(int conn)
{
    //接收缓冲区
    char buffer[1000];
    //不断接收数据
    while(1){
        CommInfo cmd;
        memset(&cmd,0,sizeof(cmd));
        int len =recv(conn,&cmd,sizeof(cmd),0);
    switch (cmd.type)
    {
        case CmdType::CT_Register:
            cout<<"注册:name:"<<cmd.name<<",passwd:"<<cmd.passwd<<endl;
            break;
        case CmdType::CT_Login:
            cout<<"登录:name:"<<cmd.name<<",passwd:"<<cmd.passwd<<endl;
            break;
        default:
            break;
    }
        //客户端发送exit或者异常结束时，退出
        if(strcmp(buffer,"exit")==0||len<=0)
            break;

        string ans="好的呢";
        int ret = send(conn,ans.c_str(),ans.length(),0);
        if(ret<=0){
            close(conn);
            break;
        }

    }
}
int main(){
    server serv(8023,"127.0.0.1");
    serv.run();//启动

}